#include"Socket.h"

int createnoblocingfd()
{
     // 初始化服务端用于监听的socket。
     int listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
     if (listenfd < 0)
     {
         perror("socket() failed"); 
         return -1;
     }
     return listenfd;
}


Socket::Socket(int fd):fd_(fd)
{
    
}

Socket::~Socket()
{
    ::close(fd_);
}

int Socket::fd() const
{
    return fd_;
}

std::string Socket::ip()
{
    return ip_;
}

uint16_t Socket::port()
{
    return port_;
}

void Socket::setaddress(InetAddress &clientaddr)
{
    // 存放客户端的地址信息
    ip_ = clientaddr.ip();
    port_ = clientaddr.port();
}

void Socket::setreuseaddr(bool on)
{
    int opt = on ? 1 : 0;
    setsockopt(fd_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//地址、端口可重用
    
}

void Socket::settcpnodelay(bool on)
{
    int opt = on ? 1 : 0;
    setsockopt(fd_,SOL_SOCKET,TCP_NODELAY,&opt,sizeof(opt));//禁用 TCP 的Nagle算法，减少发送数据延迟，要求实时发送
}

void Socket::bind(const InetAddress &servaddr)
{
    if (::bind(fd_, servaddr.addr(), sizeof(sockaddr)) < 0 )
    {
        perror("bind() failed"); 
        close(fd_); 
        exit(-1);
    }
    // 存放服务端的地址信息
    ip_ = servaddr.ip();
    port_ = servaddr.port();
}

void Socket::listen(int nn)
{
    // 在高并发服务器中，第二个参数要大一点
    if (::listen(fd_, 128) != 0 )
    {
        perror("listen() failed"); 
        close(fd_); 
        exit(-1);
    }
}

int Socket::accept(InetAddress& clientaddr)
{
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    int clientfd = accept4(fd_,(struct sockaddr*)&client,&len, SOCK_NONBLOCK);

    clientaddr.setaddr(client);

    return clientfd;
}
